<html lang="zh-CN"><head><meta charset="UTF-8"><style>.nodata  main {width:1000px;margin: auto;}</style></head><body class="nodata " style=""><div class="main_father clearfix d-flex justify-content-center " style="height:100%;"> <div class="container clearfix " id="mainBox"><main><div class="blog-content-box">
<div class="article-header-box">
<div class="article-header">
<div class="article-title-box">
<h1 class="title-article" id="articleContentId">(C卷,200分)- 模拟目录管理功能（Java & JS & Python & C）</h1>
</div>
</div>
</div>
<div id="blogHuaweiyunAdvert"></div>

        <div id="article_content" class="article_content clearfix">
        <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
        <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-044f2cf1dc.css">
                <div id="content_views" class="htmledit_views">
                    <p id="main-toc"><strong>目录</strong></p> 
<p id="main-toc-toc" style="margin-left:80px;"><a href="#main-toc" rel="nofollow">题目描述</a></p> 
<p id="%E8%BE%93%E5%85%A5%E6%8F%8F%E8%BF%B0-toc" style="margin-left:80px;"><a href="#%E8%BE%93%E5%85%A5%E6%8F%8F%E8%BF%B0" rel="nofollow">输入描述</a></p> 
<p id="%E8%BE%93%E5%87%BA%E6%8F%8F%E8%BF%B0-toc" style="margin-left:80px;"><a href="#%E8%BE%93%E5%87%BA%E6%8F%8F%E8%BF%B0" rel="nofollow">输出描述</a></p> 
<p id="%E5%A4%87%E6%B3%A8-toc" style="margin-left:80px;"><a href="#%E5%A4%87%E6%B3%A8" rel="nofollow">备注</a></p> 
<p id="%E7%94%A8%E4%BE%8B-toc" style="margin-left:80px;"><a href="#%E7%94%A8%E4%BE%8B" rel="nofollow">用例</a></p> 
<p id="%E9%A2%98%E7%9B%AE%E8%A7%A3%E6%9E%90-toc" style="margin-left:80px;"><a href="#%E9%A2%98%E7%9B%AE%E8%A7%A3%E6%9E%90" rel="nofollow">题目解析</a></p> 
<p id="%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81-toc" style="margin-left:80px;"><a href="#%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81" rel="nofollow">算法源码</a></p> 
<p id="%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81-toc" style="margin-left:120px;"><a href="#%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81" rel="nofollow">JavaScript算法源码</a></p> 
<p id="Java%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81-toc" style="margin-left:120px;"><a href="#Java%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81" rel="nofollow">Java算法源码</a></p> 
<p id="Python%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81-toc" style="margin-left:120px;"><a href="#Python%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81" rel="nofollow">Python算法源码</a></p> 
<p id="C%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81-toc" style="margin-left:120px;"><a href="#C%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81" rel="nofollow">C算法源码</a></p> 
<hr id="hr-toc" /> 
<p></p> 
<h4 id="main-toc">题目描述</h4> 
<p>实现一个模拟目录管理功能的软件&#xff0c;输入一个命令序列&#xff0c;输出最后一条命令运行结果。</p> 
<p>支持命令&#xff1a;</p> 
<ol><li>创建目录命令&#xff1a;<span style="background-color:#f9eda6;">mkdir 目录名称</span>&#xff0c;如 <span style="background-color:#f9eda6;">mkdir abc</span> 为在当前目录创建abc目录&#xff0c;如果已存在同名目录则不执行任何操作。此命令无输出。</li><li>进入目录命令&#xff1a;<span style="background-color:#f9eda6;">cd 目录名称</span>&#xff0c;如 <span style="background-color:#f9eda6;">cd abc</span> 为进入abc目录&#xff0c;特别地&#xff0c;<span style="background-color:#f9eda6;">cd ..</span> 为返回上级目录&#xff0c;如果目录不存在则不执行任何操作。此命令无输出。</li><li>查看当前所在路径命令&#xff1a;<span style="background-color:#f9eda6;">pwd</span>&#xff0c;输出当前路径字符串。</li></ol> 
<p></p> 
<p>约束&#xff1a;</p> 
<ol><li>目录名称仅支持小写字母&#xff1b;mkdir 和 cd 命令的参数仅支持单个目录&#xff0c;如&#xff1a;mkdir abc 和 cd abc&#xff1b;不支持嵌套路径和绝对路径&#xff0c;如 mkdir abc/efg&#xff0c;cd abc/efg&#xff0c;mkdir /abc/efg&#xff0c;cd /abc/efg 是不支持的。</li><li>目录符号为/&#xff0c;根目录/作为初始目录。</li><li>任何不符合上述定义的无效命令不做任何处理并且无输出。</li></ol> 
<p></p> 
<h4 id="%E8%BE%93%E5%85%A5%E6%8F%8F%E8%BF%B0">输入描述</h4> 
<p>输入 N 行字符串&#xff0c;每一行字符串是一条命令。</p> 
<p></p> 
<h4 id="%E8%BE%93%E5%87%BA%E6%8F%8F%E8%BF%B0">输出描述</h4> 
<p>输出最后一条命令运行结果字符串。</p> 
<p></p> 
<h4 id="%E5%A4%87%E6%B3%A8">备注</h4> 
<p>命令行数限制100行以内&#xff0c;目录名称限制10个字符以内。</p> 
<p></p> 
<h4 id="%E7%94%A8%E4%BE%8B">用例</h4> 
<table border="1" cellpadding="1" cellspacing="1" style="width:500px;"><tbody><tr><td style="width:86px;">输入</td><td style="width:412px;">mkdir abc<br /> cd abc<br /> pwd</td></tr><tr><td style="width:86px;">输出</td><td style="width:412px;">/abc/</td></tr><tr><td style="width:86px;">说明</td><td style="width:412px;">在根目录创建一个abc的目录并进入abc目录中查看当前目录路径&#xff0c;输出当前路径/abc/。</td></tr></tbody></table> 
<p></p> 
<h4 id="%E9%A2%98%E7%9B%AE%E8%A7%A3%E6%9E%90">题目解析</h4> 
<p>本题感觉主要是考察树形结构定义&#xff0c;以及逻辑模拟。</p> 
<p>目录结构&#xff0c;其实就是一个树形结构。一个父目录下面可以有多个直接子目录&#xff0c;而一个子目录只能有一个父目录。因此&#xff0c;本题需要定义出一个多叉树结构。</p> 
<p>关于树节点定义如下&#xff1a;</p> 
<blockquote> 
 <p>class TreeNode {<!-- --></p> 
 <p>        String dicName; // 当前目录的名字</p> 
 <p>        TreeNode father; // 当前目录的父目录</p> 
 <p>        List&lt;TreeNode&gt; children; // 当前目录的子目录</p> 
 <p>}</p> 
</blockquote> 
<p></p> 
<p>接下来&#xff0c;就是实现目录管理能力&#xff1a;</p> 
<ul><li>mkdir</li><li>cd</li><li>pwd</li></ul> 
<p></p> 
<p>实现这三个能力前&#xff0c;我们需要定义出树结构&#xff1a;</p> 
<blockquote> 
 <p>class Tree {<!-- --></p> 
 <p>        TreeNode root; // 树的根目录</p> 
 <p>        TreeNode cur; // 当前所在目录</p> 
 <p>}</p> 
</blockquote> 
<p>其中&#xff0c;tree.cur 用于指向当前所在目录&#xff0c;初始时 tree.cur &#61; tree.root。</p> 
<p></p> 
<p>mkdir&#xff0c;其实就是在 tree.cur 目录下创建一个子目录&#xff0c;但是前提是 tree.cur 下面不存在对应子目录名&#xff0c;否则不操作。mkdir操作不改变 tree.cur 指向。</p> 
<hr /> 
<p>cd&#xff0c;有两种情况&#xff1a;</p> 
<ol><li>cd ..<br /><br /> cd .. 是返回上级目录&#xff08;父目录&#xff09;&#xff0c;但是前提是 tree.cur.father 存在&#xff0c;否则不操作。如果 tree.cur.father 存在&#xff0c;则cd .. 会改变 tree.cur &#61; tree.cur.father。</li><li>cd 目录名<br /><br /> cd 目录名 是进入子目录&#xff0c;但是前提是 tree.cur 包含对应目录名的子目录&#xff0c;否则不操作。如果 存在对应子目录&#xff0c;则 cd操作会改变 tree.cur &#61; 对应子目录</li></ol> 
<hr /> 
<p>pwd 是输出当前目录的路径字符串&#xff0c;我们可以不停进行 tree.cur &#61; tree.cur.father 的倒序遍历&#xff0c;获取遍历过程中目录名tree.cur.dicName&#xff0c;直到 tree.cur &#61;&#61; NULL。最后拼接时注意反转。</p> 
<hr /> 
<p></p> 
<p>上面是目录管理功能的三个能力大致实现思路&#xff0c;具体实现根据不同语言有不同改进&#xff0c;比如 cd 目录名 功能&#xff0c;我们需要遍历 tree.cur.children 来确认对应目录名是否存在&#xff0c;这里Java&#xff0c;JS&#xff0c;Py定义 tree.cur.children 时可以使用 字典Map 来定义&#xff08;key是目录名&#xff0c;val是对应目录名的TreeNode&#xff09;&#xff0c;从而实现快速查找对应目录。</p> 
<p></p> 
<p>另外&#xff0c;本题需要对mkdir, cd, pwd的命令参数做约束&#xff1a;</p> 
<ul><li>mkdir, cd 的参数只能是1个&#xff0c;如果超过1个&#xff0c;就不进行操作</li><li>pwd 不需要参数&#xff0c;如果有参数&#xff0c;就不进行操作</li><li>mkdir&#xff0c;cd的参数&#xff08;目录名&#xff09;只能由小写字母组成&#xff0c;否则不操作</li><li>mkdir&#xff0c;cd的参数&#xff08;目录名&#xff09;不能是嵌套路径&#xff0c;或者绝对路径</li></ul> 
<p></p> 
<h4 id="%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81">算法源码</h4> 
<h5>JavaScript算法源码</h5> 
<pre><code class="language-javascript">const rl &#61; require(&#34;readline&#34;).createInterface({ input: process.stdin });
var iter &#61; rl[Symbol.asyncIterator]();
const readline &#61; async () &#61;&gt; (await iter.next()).value;

void (async function () {
  class TreeNode {
    constructor(curDicName, father) {
      this.curDicName &#61; curDicName;
      this.father &#61; father;
      this.children &#61; {};
    }
  }

  class Tree {
    constructor() {
      // root是根目录&#xff0c;根目录 / 作为初始目录
      this.root &#61; new TreeNode(&#34;/&#34;, null);
      // cur用于指向当前正在操作的目录
      this.cur &#61; this.root;
    }

    mkdir(dicName) {
      // mkdir 目录名称&#xff0c;如 mkdir abc 为在当前目录创建abc目录&#xff0c;如果已存在同名目录则不执行任何操作
      if (!this.cur.children[dicName]) {
        this.cur.children[dicName] &#61; new TreeNode(dicName &#43; &#34;/&#34;, this.cur);
      }
    }

    cd(dicName) {
      if (dicName &#61;&#61; &#34;..&#34;) {
        // cd .. 为返回上级目录&#xff0c;如果目录不存在则不执行任何操作
        if (this.cur.father !&#61; null) {
          // cur 变更指向上级目录
          this.cur &#61; this.cur.father;
        }
      } else {
        // cd 目录名称&#xff0c;如 cd abc 为进入abc目录&#xff0c;如果目录不存在则不执行任何操作
        if (this.cur.children[dicName]) {
          // cur 变更指向下级目录
          this.cur &#61; this.cur.children[dicName];
        }
      }
    }

    pwd() {
      // 输出当前路径字符串
      const arr &#61; [];

      // 倒序路径&#xff0c;即不停向上找父目录
      let cur &#61; this.cur;
      while (cur !&#61; null) {
        arr.push(cur.curDicName);
        cur &#61; cur.father;
      }

      // 反转后拼接
      return arr.reverse().join(&#34;&#34;);
    }
  }

  // 初始化目录结构
  const tree &#61; new Tree();
  // 记录最后一条命令的输出
  let lastCommandOutPut &#61; &#34;&#34;;

  outer: while (true) {
    try {
      const line &#61; await readline();

      // 本地测试解开此行
      // if (line &#61;&#61; &#34;&#34;) break;

      const tmp &#61; line.split(&#34; &#34;);
      const cmd_key &#61; tmp[0];

      if (cmd_key &#61;&#61; &#34;pwd&#34;) {
        // pwd 命令不需要参数
        if (tmp.length !&#61; 1) continue;
        lastCommandOutPut &#61; tree.pwd();
      } else if (cmd_key &#61;&#61; &#34;mkdir&#34; || cmd_key &#61;&#61; &#34;cd&#34;) {
        // 约束&#xff1a;mkdir 和 cd 命令的参数仅支持单个目录&#xff0c;如&#xff1a;mkdir abc 和 cd abc
        if (tmp.length !&#61; 2) continue;

        // 目录名
        const cmd_val &#61; tmp[1];

        if (!(cmd_key &#61;&#61; &#34;cd&#34; &amp;&amp; cmd_val &#61;&#61; &#34;..&#34;)) {
          // 目录名约束校验
          // 约束&#xff1a;目录名称仅支持小写字母
          // 约束&#xff1a;不支持嵌套路径和绝对路径&#xff0c;如 mkdir abc/efg&#xff0c;cd abc/efg&#xff0c;mkdir /abc/efg&#xff0c;cd /abc/efg 是不支持的。
          // 关于嵌套路径和绝对路径&#xff0c;我简单理解就是cmd_val含有&#39;/&#39;字符&#xff0c;可以被小写字母判断涵盖住
          for (let c of cmd_val) {
            if (c &lt; &#34;a&#34; || c &gt; &#34;z&#34;) continue outer;
          }
        }

        if (cmd_key &#61;&#61; &#34;mkdir&#34;) {
          tree.mkdir(cmd_val);
          // 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
          lastCommandOutPut &#61; &#34;&#34;;
        } else {
          tree.cd(cmd_val);
          // 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
          lastCommandOutPut &#61; &#34;&#34;;
        }
      }
    } catch (e) {
      break;
    }
  }

  console.log(lastCommandOutPut);
})();
</code></pre> 
<p></p> 
<h5 id="Java%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81">Java算法源码</h5> 
<pre><code class="language-java">import java.util.HashMap;
import java.util.Scanner;

public class Main {
  static class TreeNode {
    String curDicName;
    TreeNode father;
    HashMap&lt;String, TreeNode&gt; children;

    public TreeNode(String curDicName, TreeNode father) {
      this.curDicName &#61; curDicName;
      this.father &#61; father;
      this.children &#61; new HashMap&lt;&gt;();
    }
  }

  static class Tree {
    TreeNode root;
    TreeNode cur;

    public Tree() {
      // root是根目录&#xff0c;根目录 / 作为初始目录
      this.root &#61; new TreeNode(&#34;/&#34;, null);
      // cur用于指向当前正在操作的目录
      this.cur &#61; root;
    }

    public void mkdir(String childDicName) {
      // mkdir 目录名称&#xff0c;如 mkdir abc 为在当前目录创建abc目录&#xff0c;如果已存在同名目录则不执行任何操作
      this.cur.children.putIfAbsent(
          childDicName, new TreeNode(childDicName &#43; &#34;/&#34;, this.cur)); // 目录符号为 /
    }

    public void cd(String dicName) {
      if (dicName.equals(&#34;..&#34;)) {
        // cd .. 为返回上级目录&#xff0c;如果目录不存在则不执行任何操作
        if (this.cur.father !&#61; null) {
          // cur 变更指向上级目录
          this.cur &#61; this.cur.father;
        }
      } else {
        // cd 目录名称&#xff0c;如 cd abc 为进入abc目录&#xff0c;如果目录不存在则不执行任何操作
        if (this.cur.children.containsKey(dicName)) {
          // cur 变更指向下级目录
          this.cur &#61; this.cur.children.get(dicName);
        }
      }
    }

    public String pwd() {
      // 输出当前路径字符串
      StringBuilder sb &#61; new StringBuilder();

      // 倒序路径&#xff0c;即不停向上找父目录
      TreeNode cur &#61; this.cur;
      while (cur !&#61; null) {
        // 头插目录名&#xff0c;保证路径中目录层级正确
        sb.insert(0, cur.curDicName);
        cur &#61; cur.father;
      }

      return sb.toString();
    }
  }

  public static void main(String[] args) {
    Scanner sc &#61; new Scanner(System.in);

    // 初始化目录结构
    Tree tree &#61; new Tree();

    // 记录最后一条命令的输出
    String lastCommandOutPut &#61; &#34;&#34;;

    outer:
    while (sc.hasNextLine()) {
      String line &#61; sc.nextLine();

      // 本地测试解开此行
      //      if (line.equals(&#34;&#34;)) break;

      String[] tmp &#61; line.split(&#34; &#34;);

      String cmd_key &#61; tmp[0];

      if (cmd_key.equals(&#34;pwd&#34;)) {
        // pwd 命令不需要参数
        if (tmp.length !&#61; 1) continue;
        lastCommandOutPut &#61; tree.pwd();
      } else if (cmd_key.equals(&#34;mkdir&#34;) || cmd_key.equals(&#34;cd&#34;)) {
        // 约束&#xff1a;mkdir 和 cd 命令的参数仅支持单个目录&#xff0c;如&#xff1a;mkdir abc 和 cd abc
        if (tmp.length !&#61; 2) continue;

        // 目录名
        String cmd_val &#61; tmp[1];

        if (!(cmd_key.equals(&#34;cd&#34;) &amp;&amp; cmd_val.equals(&#34;..&#34;))) {
          // 目录名约束校验
          // 约束&#xff1a;目录名称仅支持小写字母
          // 约束&#xff1a;不支持嵌套路径和绝对路径&#xff0c;如 mkdir abc/efg&#xff0c;cd abc/efg&#xff0c;mkdir /abc/efg&#xff0c;cd /abc/efg 是不支持的。
          // 关于嵌套路径和绝对路径&#xff0c;我简单理解就是cmd_val含有&#39;/&#39;字符&#xff0c;可以被小写字母判断涵盖住
          for (int i &#61; 0; i &lt; cmd_val.length(); i&#43;&#43;) {
            char c &#61; cmd_val.charAt(i);
            if (c &lt; &#39;a&#39; || c &gt; &#39;z&#39;) continue outer;
          }
        }

        if (cmd_key.equals(&#34;mkdir&#34;)) {
          tree.mkdir(cmd_val);

          // 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
          lastCommandOutPut &#61; &#34;&#34;;
        } else {
          tree.cd(cmd_val);
          // 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
          lastCommandOutPut &#61; &#34;&#34;;
        }
      }
    }

    System.out.println(lastCommandOutPut);
  }
}
</code></pre> 
<p></p> 
<h5 id="Python%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81" style="background-color:transparent;">Python算法源码</h5> 
<pre><code class="language-python">class TreeNode:
    def __init__(self, curDicName, father):
        self.curDicName &#61; curDicName
        self.father &#61; father
        self.children &#61; {}


class Tree:
    def __init__(self):
        # root是根目录&#xff0c;根目录 / 作为初始目录
        self.root &#61; TreeNode(&#34;/&#34;, None)
        # cur用于指向当前正在操作的目录
        self.cur &#61; self.root

    def mkdir(self, dicName):
        # mkdir 目录名称&#xff0c;如 mkdir abc 为在当前目录创建abc目录&#xff0c;如果已存在同名目录则不执行任何操作
        self.cur.children.setdefault(dicName, TreeNode(dicName &#43; &#34;/&#34;, self.cur))  # 目录符号为 /

    def cd(self, dicName):
        if dicName &#61;&#61; &#34;..&#34;:
            # cd .. 为返回上级目录&#xff0c;如果目录不存在则不执行任何操作
            if self.cur.father is not None:
                # cur 变更指向上级目录
                self.cur &#61; self.cur.father
        else:
            # cd 目录名称&#xff0c;如 cd abc 为进入abc目录&#xff0c;如果目录不存在则不执行任何操作
            if self.cur.children.get(dicName) is not None:
                # cur 变更指向下级目录
                self.cur &#61; self.cur.children[dicName]

    def pwd(self):
        # 输出当前路径字符串
        lst &#61; []

        # 倒序路径&#xff0c;即不停向上找父目录
        cur &#61; self.cur
        while cur is not None:
            lst.append(cur.curDicName)
            cur &#61; cur.father

        # 反转后拼接
        lst.reverse()

        return &#34;&#34;.join(lst)


# 算法逻辑
# 初始化目录结构
tree &#61; Tree()

# 记录最后一条命令的输出
lastCommandOutput &#61; &#34;&#34;

while True:
    try:
        line &#61; input()

        # 本地测试解开此行
        # if line &#61;&#61; &#34;&#34;:
        #     break

        tmp &#61; line.split()
        cmd_key &#61; tmp[0]

        if cmd_key &#61;&#61; &#34;pwd&#34;:
            # pwd 命令不需要参数
            if len(tmp) !&#61; 1:
                continue
            lastCommandOutput &#61; tree.pwd()
        elif cmd_key &#61;&#61; &#34;mkdir&#34; or cmd_key &#61;&#61; &#34;cd&#34;:
            # 约束&#xff1a;mkdir 和 cd 命令的参数仅支持单个目录&#xff0c;如&#xff1a;mkdir abc 和 cd abc
            if len(tmp) !&#61; 2:
                continue

            # 目录名
            cmd_val &#61; tmp[1]

            # 目录名约束校验
            # 约束&#xff1a;目录名称仅支持小写字母
            # 约束&#xff1a;不支持嵌套路径和绝对路径&#xff0c;如 mkdir abc/efg&#xff0c;cd abc/efg&#xff0c;mkdir /abc/efg&#xff0c;cd /abc/efg 是不支持的。
            # 关于嵌套路径和绝对路径&#xff0c;我简单理解就是cmd_val含有&#39;/&#39;字符&#xff0c;可以被小写字母判断涵盖住
            if not (cmd_val.isalpha() and cmd_val.islower()) and not (cmd_key &#61;&#61; &#39;cd&#39; and cmd_val &#61;&#61; &#39;..&#39;):
                continue

            if cmd_key &#61;&#61; &#34;mkdir&#34;:
                tree.mkdir(cmd_val)
                # 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
                lastCommandOutput &#61; &#34;&#34;
            else:
                tree.cd(cmd_val)
                # 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
                lastCommandOutput &#61; &#34;&#34;
    except:
        break

print(lastCommandOutput)</code></pre> 
<p></p> 
<h5 id="C%E7%AE%97%E6%B3%95%E6%BA%90%E7%A0%81" style="background-color:transparent;">C算法源码</h5> 
<pre><code class="language-cpp">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

/** 树节点 **/
typedef struct TreeNode {
    char curDicName[11]; // 当前目录名
    struct TreeNode *father; // 父目录&#xff08;只能有一个&#xff09;
    struct LinkedList *children; // 子目录&#xff08;可以有多个&#xff0c;这里使用链表记录&#xff09;
} TreeNode;

/** 链表节点 **/
typedef struct ListNode {
    TreeNode *ele; // 链表用于记录多个子目录&#xff0c;因此链表节点的内容就是树节点
    struct ListNode *next;
} ListNode;

/** 链表 **/
typedef struct LinkedList {
    ListNode *head;
    ListNode *tail;
    int size;
} LinkedList;

/** 树 **/
typedef struct Tree {
    TreeNode *root; // 记录树根节点
    TreeNode *cur; // 记录当前目录对应的节点
} Tree;

/**  链表结构方法  **/
// 初始化链表
LinkedList *new_LinkedList() {
    LinkedList *link &#61; (LinkedList *) malloc(sizeof(LinkedList));

    link-&gt;head &#61; NULL;
    link-&gt;tail &#61; NULL;
    link-&gt;size &#61; 0;

    return link;
}

// 尾插链表
void addLast_LinkedList(LinkedList *link, TreeNode *ele) {
    ListNode *listNode &#61; (ListNode *) malloc(sizeof(ListNode));
    listNode-&gt;ele &#61; ele;
    listNode-&gt;next &#61; NULL;

    if(link-&gt;size &#61;&#61; 0) {
        link-&gt;head &#61; listNode;
        link-&gt;tail &#61; listNode;
    } else {
        link-&gt;tail-&gt;next &#61; listNode;
        link-&gt;tail &#61; listNode;
    }

    link-&gt;size&#43;&#43;;
}

// 遍历链表&#xff0c;获取指定节点的内容
TreeNode *get_LinkedList(LinkedList *link, char *dicName) {
    ListNode *curListNode &#61; link-&gt;head;
    while (curListNode !&#61; NULL) {
        if (strcmp(curListNode-&gt;ele-&gt;curDicName, dicName) &#61;&#61; 0) {
            return curListNode-&gt;ele;
        }
        curListNode &#61; curListNode-&gt;next;
    }
    return NULL;
}

/**  树形结构方法  **/
TreeNode *new_TreeNode(char *curDicName, TreeNode *father) {
    TreeNode *treeNode &#61; (TreeNode *) calloc(1, sizeof(TreeNode));

    strcpy(treeNode-&gt;curDicName, curDicName);
    treeNode-&gt;father &#61; father;
    treeNode-&gt;children &#61; new_LinkedList();

    return treeNode;
}

// 初始化树
Tree *new_Tree() {
    Tree *tree &#61; (Tree *) malloc(sizeof(Tree));

    // 由于目录名结尾都要带&#39;/&#39;&#xff0c;因此可以认为根目录是空串&#xff0c;后期拼接时再尾部追加&#39;/&#39;
    // 另外根目录没有父目录&#xff0c;因此父目录设置为NULL
    tree-&gt;root &#61; new_TreeNode(&#34;&#34;, NULL);
    // 初始时&#xff0c;当前目录就是根目录
    tree-&gt;cur &#61; tree-&gt;root;

    return tree;
}

// 创建指定目录
void mkdir_Tree(Tree *tree, char *dicName) {
    TreeNode *p &#61; get_LinkedList(tree-&gt;cur-&gt;children, dicName);

    // mkdir 目录名称&#xff0c;如 mkdir abc 为在当前目录创建abc目录&#xff0c;如果已存在同名目录则不执行任何操作
    if (p !&#61; NULL) {
        return;
    }

    TreeNode *treeNode &#61; new_TreeNode(dicName, tree-&gt;cur);
    addLast_LinkedList(tree-&gt;cur-&gt;children, treeNode);
}

// 跳转到指定目录
void cd_Tree(Tree *tree, char *dicName) {
    if (strcmp(dicName, &#34;..&#34;) &#61;&#61; 0) {
        // cd .. 为返回上级目录&#xff0c;如果目录不存在则不执行任何操作
        if (tree-&gt;cur-&gt;father !&#61; NULL) {
            // cur 变更指向上级目录
            tree-&gt;cur &#61; tree-&gt;cur-&gt;father;
        }
    } else {
        TreeNode *p &#61; get_LinkedList(tree-&gt;cur-&gt;children, dicName);

        // cd 目录名称&#xff0c;如 cd abc 为进入abc目录&#xff0c;如果目录不存在则不执行任何操作
        if (p !&#61; NULL) {
            // cur 变更指向下级目录
            tree-&gt;cur &#61; p;
        }
    }
}

// 输出当前路径字符串
char *pwd_Tree(Tree *tree) {
    char *tmp &#61; (char *) calloc(10000, sizeof(char));
    char *res &#61; (char *) calloc(10000, sizeof(char));

    // 倒序路径&#xff0c;即不停向上找父目录
    TreeNode *cur &#61; tree-&gt;cur;
    while (cur !&#61; NULL) {
        strcpy(tmp, res);

        strcpy(res, cur-&gt;curDicName);
        strcat(res, &#34;/&#34;);
        strcat(res, tmp);
        cur &#61; cur-&gt;father;
    }

    return res;
}

int main() {
    // 初始化目录结构
    Tree *tree &#61; new_Tree();

    // 记录最后一条命令的输出
    char lastCommandOutPut[10000];

    char s[50];
    while (gets(s)) {
        // 本地测试解开此行注释
         if(strlen(s) &#61;&#61; 0) break;

        char *cmd_key &#61; strtok(s, &#34; &#34;);
        char *cmd_val &#61; strtok(NULL, &#34; &#34;);

        if (strcmp(cmd_key, &#34;pwd&#34;) &#61;&#61; 0) {
            // pwd 命令不需要参数
            if (cmd_val !&#61; NULL) {
                continue;
            }
            strcpy(lastCommandOutPut, pwd_Tree(tree));
        } else if (strcmp(cmd_key, &#34;mkdir&#34;) &#61;&#61; 0 || strcmp(cmd_key, &#34;cd&#34;) &#61;&#61; 0) {
            // 约束&#xff1a;mkdir 和 cd 命令的参数仅支持单个目录&#xff0c;如&#xff1a;mkdir abc 和 cd abc
            if (cmd_val &#61;&#61; NULL) continue;

            char *p &#61; strtok(NULL, &#34; &#34;);
            if (p !&#61; NULL) continue;

            if(!(strcmp(cmd_key, &#34;cd&#34;) &#61;&#61; 0 &amp;&amp; strcmp(cmd_val, &#34;..&#34;) &#61;&#61; 0)) {
                unsigned long long len &#61; strlen(cmd_val);

                // 目录名约束校验
                // 约束&#xff1a;目录名称仅支持小写字母
                // 约束&#xff1a;不支持嵌套路径和绝对路径&#xff0c;如 mkdir abc/efg&#xff0c;cd abc/efg&#xff0c;mkdir /abc/efg&#xff0c;cd /abc/efg 是不支持的。
                // 关于嵌套路径和绝对路径&#xff0c;我简单理解就是cmd_val含有&#39;/&#39;字符&#xff0c;可以被小写字母判断涵盖住
                int i &#61; 0;
                for (; i &lt; len; i&#43;&#43;) {
                    char c &#61; cmd_val[i];

                    if (c &lt; &#39;a&#39; || c &gt; &#39;z&#39;) {
                        break;
                    }
                }

                if(i !&#61; len) {
                    continue;
                }
            }

            if(strcmp(cmd_key, &#34;mkdir&#34;) &#61;&#61; 0) {
                mkdir_Tree(tree, cmd_val);
                // 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
                memset(lastCommandOutPut, &#39;\0&#39;, strlen(lastCommandOutPut));
            } else {
                cd_Tree(tree, cmd_val);
                // 题目进要求输出最后一个命令的运行结果&#xff0c;因此&#xff0c;对于无输出的命令&#xff0c;我认为需要覆盖掉前面的命令的输出结果
                memset(lastCommandOutPut, &#39;\0&#39;, strlen(lastCommandOutPut));
            }
        }
    }

    puts(lastCommandOutPut);

    return 0;
}</code></pre>
                </div>
        </div>
        <div id="treeSkill"></div>
        <div id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"></div>
    <script>
  $(function() {
    setTimeout(function () {
      var mathcodeList = document.querySelectorAll('.htmledit_views img.mathcode');
      if (mathcodeList.length > 0) {
        for (let i = 0; i < mathcodeList.length; i++) {
          if (mathcodeList[i].naturalWidth === 0 || mathcodeList[i].naturalHeight === 0) {
            var alt = mathcodeList[i].alt;
            alt = '\\(' + alt + '\\)';
            var curSpan = $('<span class="img-codecogs"></span>');
            curSpan.text(alt);
            $(mathcodeList[i]).before(curSpan);
            $(mathcodeList[i]).remove();
          }
        }
        MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
      }
    }, 1000)
  });
</script>
</div></html>